<template>
  <div class="form-control w-full">
    <!-- <label v-if="label" class="label">
      <span class="label-text">
        {{ label }}
        <span v-if="required" class="text-error ml-1">*</span>
      </span>
    </label> -->
    <div
      :class="{ 'border-2 border-dashed rounded-lg p-4 text-center cursor-pointer hover:border-primary': true, 'border-error': props.required && hasInteracted && fileList.length === 0, 'border-base-300': !(props.required && hasInteracted && fileList.length === 0) }"
      @dragover.prevent
      @drop.prevent="handleDrop"
      @click="triggerFileInput"
    >
      <input
        type="file"
        ref="fileInput"
        class="hidden"
        multiple
        :accept="accept"
        @change="handleFileChange"
        :disabled="disabled"
      />
      <div class="flex flex-col items-center gap-2">
        <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
        </svg>
        <span>点击或拖拽文件到此处上传</span>
        <span class="text-sm text-base-content/70">{{ acceptText }}</span>
        <span class="text-sm text-base-content/70">支持同时上传多个文件</span>
      </div>
    </div>

    <div v-if="fileList.length > 0" class="mt-4 space-y-2">
      <div class="flex justify-between items-center mb-2">
        <span class="text-sm">已选择 {{ fileList.length }} 个文件</span>
        <button
          v-if="fileList.length > 0"
          class="clear-all-btn"
          @click="clearAllFiles"
          :disabled="!areAllFilesUploaded()"
        >
          清空所有
        </button>
      </div>
      <div
        v-for="(file, index) in fileList"
        :key="index"
        class="flex items-center justify-between p-2 bg-base-200 rounded-lg"
      >
        <div class="flex-1 flex items-center gap-2 overflow-hidden">
          <svg class="h-5 w-5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
          </svg>
          <div class="flex flex-col w-full overflow-hidden">
            <div class="flex justify-between items-center">
              <span class="truncate">{{ file.name }}</span>
              <span class="text-xs text-base-content/70 ml-2">{{ uploadProgress[file.name] || 0 }}%</span>
            </div>
            <div class="w-full bg-base-300 rounded-full h-1.5 mt-1">
              <div class="bg-primary h-1.5 rounded-full transition-all duration-300" :style="{ width: `${uploadProgress[file.name] || 0}%` }"></div>
            </div>
            <span class="text-xs text-base-content/70 mt-1">{{ formatFileSize(file.size) }}</span>
          </div>
        </div>
        <button
          class="delete-btn"
          @click.stop="removeFile(index)"
          :disabled="disabled || uploadProgress[file.name] !== 100"
        >
          <svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
          </svg>
        </button>
      </div>
    </div>

    <label v-if="error" class="label">
      <span class="label-text-alt text-error">{{ error }}</span>
    </label>
    <label v-if="props.required && hasInteracted && fileList.length === 0 || error && error.includes('格式不支持')" class="label">
      <span class="label-text-alt text-error">请上传格式为CSV、DAT、DB、MDB或TXT格式的文件</span>
    </label>
  </div>
  <!-- 消息提示组件 -->
  <Message ref="messageRef" />
</template>

<script setup lang="ts">
import { ref, computed, onMounted, reactive } from 'vue';
import fileImportApi from "@/views/fileImport/fileImport.api.ts";
import {useTimestampStore} from "@/stores/timestampStore.ts";
import Message from '@/components/BaseComponents/Message.vue'
const messageRef = ref<InstanceType<typeof Message> | null>(null)
interface Props {
  modelValue: File[];
  path?:string;
  label?: string;
  name?:string;
  error?: string;
  disabled?: boolean;
  multiple?: boolean;
  accept?: string;
  maxSize?: number; // 单位：MB
  required?: boolean; // 是否必填
}

const props = withDefaults(defineProps<Props>(), {
  disabled: false,
  multiple: true, // 默认改为多文件上传
  accept: '.csv,.dat,.db,.mdb,.txt', // 支持多种文件格式
  maxSize: 1024, // 默认单个文件最大1GB
  required: false
});

const hasInteracted = ref(false);

const emit = defineEmits<{
  (e: 'update:modelValue', files: File[]): void;
  (e: 'error', message: string): void;
  (e: 'file-uploaded', file: { name: string; raw: File }): void;
  (e: 'upload-progress', progress: number): void;
}>();

const fileInput = ref<HTMLInputElement | null>(null);
const fileList = computed(() => props.modelValue || []);
const uploadProgress = reactive<{ [key: string]: number }>({});

const acceptText = computed(() => {
  const sizeText = props.maxSize >= 1024
    ? `${(props.maxSize / 1024).toFixed(1)}GB`
    : `${props.maxSize}MB`;

  return `支持CSV、DAT、DB、MDB和TXT格式，单个文件最大 ${sizeText}`;
});

const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 Bytes';

  const k = 1024;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};

const validateFile = (file: File): boolean => {
  // 检查文件大小 (maxSize单位是MB，需转换为字节)
  if (file.size > props.maxSize * 1024 * 1024) {
    const sizeText = props.maxSize >= 1024
      ? `${(props.maxSize / 1024).toFixed(1)}GB`
      : `${props.maxSize}MB`;
    emit('error', `文件 "${file.name}" 大小超过限制 (最大 ${sizeText})`);
    return false;
  }

  // 检查文件类型
  if (props.accept !== '*') {
    const acceptTypes = props.accept.split(',').map(type => type.trim());
    const fileType = file.type || `application/${file.name.split('.').pop()}`;
    if (!acceptTypes.some(type => {
      // 处理 .jpg 这样的扩展名匹配
      if (type.startsWith('.')) {
        const ext = `.${file.name.split('.').pop()}`.toLowerCase();
        return ext === type.toLowerCase();
      }
      // 处理 image/* 这样的MIME类型匹配
      return fileType.match(new RegExp(type.replace('*', '.*')));
    })) {
      emit('error', `文件 "${file.name}" 格式不支持`);
      return false;
    }
  }
  return true;
};
const fileNames = ref('');
const handleFiles = async (files: FileList) => {
  const validFiles = Array.from(files).filter(validateFile);
  const batchId = useTimestampStore().getTimestamp();
  if (validFiles.length > 0) {
    // 检查并替换同名文件
    const updatedFileList = [...fileList.value];
    validFiles.forEach(newFile => {
      const existingIndex = updatedFileList.findIndex(f => f.name === newFile.name);
      if (existingIndex >= 0) {
        updatedFileList.splice(existingIndex, 1, newFile);
      } else {
        updatedFileList.push(newFile);
      }
    });
    emit('update:modelValue', updatedFileList);

    for (const file of validFiles) {
      // 检查文件名是否已存在
      if (!fileNames.value.includes(file.name + ',')) {
        fileNames.value += file.name + ',';
      }
      const chunkSize = 15 * 1024 * 1024;
      const totalChunks = Math.ceil(file.size / chunkSize);
      const chunks = [];
      // 初始化文件进度
      uploadProgress[file.name] = 0;
      // 准备所有分片的上传任务
      for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
        const start = chunkIndex * chunkSize;
        const end = Math.min(start + chunkSize, file.size);
        const chunk = file.slice(start, end);
        const formData = new FormData();
        formData.append('file', chunk, file.name);
        formData.append('chunkIndex', chunkIndex.toString());
        formData.append('totalChunks', totalChunks.toString());
        formData.append('fileName', file.name);
        formData.append('batchId', batchId.toString());
        chunks.push({ formData, chunkIndex });
      }

      // 并发上传所有分片
      const uploadedChunks = new Set();
      await Promise.all(chunks.map(async ({ formData, chunkIndex }) => {
        try {
          const response:any = await fileImportApi.importFileChunk(formData);
          if (response && response.code === 200) {
            uploadedChunks.add(chunkIndex);
            // 更新文件的实际上传进度
            const progress = Math.round((uploadedChunks.size / totalChunks) * 100);
            uploadProgress[file.name] = progress;
            emit('upload-progress', progress);
          } else {
            console.error('分片上传失败');
            // 请求失败时清除文件名
            fileNames.value = '';
            emit('error', response?.msg || `文件 "${file.name}" 上传失败`);
          }
        } catch (error: any) {
          console.error('上传分片失败:', error);
          messageRef.value?.show({
            type: 'warning',
            content: error.response.data.msg,
            duration: 3000
          });
          // 请求失败时清除文件名
          fileNames.value = '';
          emit('error', `文件 "${file.name}" 上传失败`);
        }
      }));
      // 所有分片上传完成后发送文件上传完成事件
      if (uploadedChunks.size === totalChunks) {
        emit('file-uploaded', { name: file.name, raw: file });
      }
    }
  }
};

const handleFileChange = (event: Event) => {
  const target = event.target as HTMLInputElement;
  if (target.files) {
    handleFiles(target.files);
  }
  target.value = ''; // 重置input，允许选择相同文件
};

const handleDrop = (event: DragEvent) => {
  if (event.dataTransfer?.files) {
    hasInteracted.value = true;
    // 处理拖拽文件，不再区分单文件/多文件模式
    handleFiles(event.dataTransfer.files);
  }
};

const triggerFileInput = () => {
  if (!props.disabled && fileInput.value) {
    hasInteracted.value = true;
    fileInput.value.click();
  }
};

const removeFile = (index: number) => {
  const file = fileList.value[index];
  let param = {"files":file.name}
  fileImportApi.removeChunkFiles(param).then((res:any) =>{
    if (res && res == 200) {
      console.log("清除文件")
    }
  }).catch((error: any) => {
    messageRef.value?.show({
      type: 'warning',
      content: error.response.data.msg,
      duration: 3000
    });
  })

  if (file) {
    delete uploadProgress[file.name];
    // 从 fileNames 中移除对应的文件名
    const fileNamesArray = fileNames.value.split(',').filter(Boolean);
    const indexToRemove = fileNamesArray.indexOf(file.name);
    if (indexToRemove > -1) {
      fileNamesArray.splice(indexToRemove, 1);
      fileNames.value = fileNamesArray.join(',') + (fileNamesArray.length > 0 ? ',' : '');
    }
  }
  const newFiles = [...fileList.value];
  newFiles.splice(index, 1);
  emit('update:modelValue', newFiles);
};

const clearAllFiles = () => {
  let param = {"files":fileNames.value.slice(0, -1)}
  fileImportApi.removeChunkFiles(param).then((res:any) =>{
      if (res && res == 200) {
        console.log("清除所有文件")
      }
  }).catch((error: any) => {
    messageRef.value?.show({
      type: 'warning',
      content: error.response.data.msg,
      duration: 3000
    });
  })
  Object.keys(uploadProgress).forEach(key => delete uploadProgress[key]);
  // 清空 fileNames
  fileNames.value = '';
  emit('update:modelValue', []);
};

function getUploadedFiles() {
  return fileList.value.map(file => ({
    name: file.name,
    raw: file
  }))
}

// 检查所有文件是否都已上传完成
function areAllFilesUploaded() {
  if (fileList.value.length === 0) return true;
  return fileList.value.every(file => uploadProgress[file.name] === 100);
}

// 暴露方法给父组件
defineExpose({
  getUploadedFiles,
  fileNames,
  areAllFilesUploaded,
  clearAllFiles
})
onMounted(() => {
  fileNames.value = '';
  // 创建时间戳
  useTimestampStore().createTimestamp();
})

// 处理单个文件上传

</script>
<style scoped>
.delete-btn {
  width: 2rem;
  height: 2rem;
  border-radius: 9999px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 0;
  transition: background-color 0.2s;
}

.delete-btn:hover {
  background-color: rgba(0, 0, 0, 0.1);
}

.delete-btn:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

.clear-all-btn {
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  border: 1px solid #ef4444;
  border-radius: 0.375rem;
  color: #ef4444;
  background: transparent;
  cursor: pointer;
  transition: all 0.2s;
}

.dark-mode .clear-all-btn{
    color: var(--error-color) !important;
    border: 1px solid var(--error-color) !important;
    background: var(--btn-color) !important;
    box-shadow: inset 0 0 5px var(--btn-shadow-color) !important;
}
.dark-mode .clear-all-btn:hover {
    background: var(--error-color) !important;
    color: var(--text-color) !important;
}

.clear-all-btn:hover:not(:disabled) {
  background-color: #fef2f2;
}

.clear-all-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* 深色模式适配 */
.dark .border-base-300 {
  border-color: #d1d5db !important;
}

.dark .bg-base-200 {
  background-color: #ffffff !important;
}

.dark .bg-base-300 {
  background-color: #f3f4f6 !important;
}

.dark .text-base-content\/70 {
  color: #6b7280 !important;
}

.dark .hover\:border-primary:hover {
  border-color: #1e40af !important;
}

.dark-mode .clear-all-btn{
    color: var(--error-color) !important;
    border: 1px solid var(--error-color) !important;
    background: var(--btn-color) !important;
    box-shadow: inset 0 0 5px var(--btn-shadow-color) !important;
}

.dark .clear-all-btn:hover:not(:disabled) {
  background-color: #f3f4f6;
  border-color: #9ca3af;
}

.dark .bg-primary {
  background-color: #1e40af !important;
}

@media (max-width: 1024px) {
  .delete-btn {
    width: 1.5rem !important;
    height: 1.5rem !important;
  }

  .delete-btn svg {
    width: 14px !important;
    height: 14px !important;
  }

  .clear-all-btn {
    padding: 0.35rem 0.75rem !important;
    font-size: 12px !important;
  }

  .label-text {
    font-size: 12px !important;
  }

  .text-sm {
    font-size: 11px !important;
  }

  .text-xs {
    font-size: 10px !important;
  }

  .h-6 {
    height: 1.25rem !important;
  }

  .w-6 {
    width: 1.25rem !important;
  }

  .h-5 {
    height: 1.125rem !important;
  }

  .w-5 {
    width: 1.125rem !important;
  }

  .h-4 {
    height: 1rem !important;
  }

  .w-4 {
    width: 1rem !important;
  }

  .p-4 {
    padding: 0.75rem !important;
  }

  .p-2 {
    padding: 0.5rem !important;
  }

  .gap-2 {
    gap: 0.5rem !important;
  }

  .mt-4 {
    margin-top: 0.75rem !important;
  }

  .mb-2 {
    margin-bottom: 0.5rem !important;
  }

  .mt-1 {
    margin-top: 0.25rem !important;
  }

  .rounded-lg {
    border-radius: 0.375rem !important;
  }

  .h-1\.5 {
    height: 0.25rem !important;
  }
}
</style>
